; Hello World Program - asmtutor.com
; Compile with: nasm -f elf helloworld.asm
; Link with (64 bit systems require elf_i386 option): ld -m elf_i386 helloworld.o -o helloworld
; Run with: ./helloworld

; 数据段 数据段用于存储程序中使用的静态变量和常量。
SECTION .data
; 字符串 "Hello World!" 被存储在 msg 标签所代表的内存位置上，并以 0Ah 作为结束标志。
; 其汇编结果为 48 65 6C 6C 6F 20 57 6F 72 6C 64 21 0A
; msg 是一个标签（label），用于标识存储字符串的位置。
; db 指令用于定义字节数据（byte data）。在这里，它指示编译器将后面的数据作为字节存储。
; 'Hello World!', 0Ah 是实际的数据部分。单引号之间的内容是字符串本身，以零终止符（null terminator）0Ah 结尾。
msg     db      'Hello World!', 0Ah     ; assign msg variable with your message string

; 代码段 用于存放可执行指令的代码。这个段通常包含了程序的主要逻辑和函数定义。
SECTION .text
; 这段汇编语言使用了 global 指令来声明一个全局符号 _start。
; 在汇编语言中，全局符号（global symbol）是可以在不同文件或模块之间进行引用的标识符。通过使用 global 指令，我们可以将一个符号标记为全局，以便其他模块可以引用它。
; 在这个例子中，_start 被声明为一个全局符号。一般情况下，_start 是程序的起始点，即程序开始执行的地方。其他模块可以通过引用 _start 来调用该程序的入口点。
; 需要注意的是，这只是一个符号的声明，并没有定义具体的代码逻辑。后续的汇编指令才会构成实际的代码。
global  _start

; _start 是程序的入口标签，表示代码从这里开始执行。
_start: 
    ; ======================
    ; 这段汇编语言用于在标准输出中打印字符串。
    ; 写文件系统调用
    ; // 参数fd是文件句柄，buf是用户缓冲区，count是欲写字节数。
    ; int sys_write(unsigned int fd,char * buf,int count)
    ; ======================
    ; mov edx, 13 将字符串的长度13存储在寄存器edx中。
    mov     edx, 13     ; number of bytes to write - one for each letter plus 0Ah (line feed character)
    ; mov ecx, msg 将消息字符串的内存地址存储到寄存器ecx中。
    mov     ecx, msg    ; move the memory address of our message string into ecx
    ; mov ebx, 1 将值1存储到寄存器ebx中。这个值表示要写入的文件描述符，1代表标准输出(STDOUT)。
    mov     ebx, 1      ; write to the STDOUT file
    ; mov eax, 4 将值4存储到寄存器eax中。这个值是系统调用号，用于调用写入操作(SYS_WRITE)。
    mov     eax, 4      ; invoke SYS_WRITE (kernel opcode 4)
    ; int 80h 触发软中断，将控制权转交给内核来处理系统调用。此时，寄存器中的值将被传递给内核，执行相应的操作。
    int     80h